import 'package:EZ_Batter/src/bluetooth/send_data.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_kit_plus/flutter_kit.dart';
import 'package:get/get.dart';

class GlobalModel {
  static final GlobalModel instance = GlobalModel._internal();
  factory GlobalModel() => instance;
  GlobalModel._internal();

  ///总电压。
  ///单位10mV
  double v = 0;

  ///每一串单体的电压
  List<double> list_v = [];

  ///平均电压
  double get average_v {
    return (v / batter_num).roundDouble(2);
  }

  ///功率 = 电压 * 电流
  double get power {
    return (GlobalModel().v * GlobalModel().a).roundDouble(1);
  }

  ///电流。
  ///单位10mA。带符号型16进制数，通过电流判断电池充放电状态，充电为正，放电为负。例如充电1A，传输数值为0x0064,放电1A传输数值为0X10000 -0X0064 = 0Xff9c;
  double a = 0;

  ///剩余电容。
  ///单位 10mAh
  double c = 0;

  ///标准电容
  ///单位 10mAh
  double total_c = 0;

  ///循环次数
  int repeat = 0;

  ///生产日期
  ///采用2个字节传送比如0x2078,其中日期为最低5为：0x2078&0x1f = 24表示日期;月份（0x2078>>5）&0x0f= 0x03表示3月;年份就为2000+ (0x2078>>9) = 2000 + 0x10 =2016
  String product = '';

  ///均衡状态
  ///每一个bit则表示每一串均衡，0为关闭，1为打开表示1~16串
  String balanced1 = '';

  ///均衡状态
  ///每一个bit则表示每一串均衡，0为关闭，1为打开表示17~32串，最高支持32串
  String balanced2 = '';

  ///保护状态
  ///每一个bit表示一种保护状态，0为未保护，1发生保护
  String protect = '';

  ///软件版本
  String version = '';

  ///表示剩余容量百分比
  int rsoc = 0;

  ///MOS指示状态，bit0表示充电MOS，bit1表示放电MOS，0表示MOS关闭，1表示打开 =0x03表示都是打开状态
  ///BIT2表示限流模块是否开启，1为打开，0为关闭
  ///Bit3：表示加热是否开启，1为正在加热中，0为关闭。
  ///其中BIT7用来表示电流容量单位，如果最高位为1则表示电流容量单位是0.1A/0.1Ah V9增加,暂时未使用
  String fet = '';

  ///电池串数
  int batter_num = 0;

  ///ntc温控个数
  int ntc_num = 0;

  ///ntc内容，即温度
  List<double> ntc_list = [];

  ///平均摄氏度
  double get average_dc {
    return ntc_list.isEmpty ? 0 : (ntc_list.reduce((a, b) => a + b) / ntc_list.length).roundDouble(1);
  }

  ///平均华氏度
  double get average_df {
    return ntc_list.isEmpty ? 0 : (9 / 5.0 * average_dc + 32).roundDouble(1);
  }

  ///充电，fet的bit0 == 1表示充电
  bool get isCharge {
    // return fet.isEmpty ? false : fet[fet.length - 1] == '1';
    return a > 0;
  }

  ///放电，fet的bit1 == 1表示放电
  bool get disCharge {
    // return fet.isEmpty ? false : fet[fet.length - 2] == '1';
    return a < 0;
  }

  ///限流模块是否开启， fet的bit2 == 1 表示开启
  bool get limit {
    return fet.isEmpty ? false : fet[fet.length - 3] == '1';
  }

  ///加热是否开启，fet的bit3 == 1 表示开启
  bool get hot {
    return fet.isEmpty ? false : fet[fet.length - 4] == '1';
  }

  bool openSoc = false;
  String get status {
    if (isCharge) {
      return 'CHARGING';
    } else if (disCharge) {
      return 'DISCHARGE';
    } else {
      return 'STATIC';
    }
  }

  static List<int> temp = [];
  static void update(List<int> bytes) {
    ///每次收到 0x77 为标志，才算完整的数据
    if (bytes.first == 0xDD || (temp.first == 0xDD && temp.last == 0x77)) {
      temp = bytes;
    } else {
      temp += bytes;
    }

    if (temp.first != 0xDD || temp.last != 0x77) {
      return;
    }

    List<int> check_bytes = temp.sublist(2, temp.length - 3);
    List<int> crc = SendData.crc(check_bytes);
    bool isEqual = const ListEquality().equals(crc, temp.sublist(temp.length - 3, temp.length - 1));
    if (!isEqual) {
      print('===========>.  校验失败');
      return;
    }

    switch (temp.sublist(0, 2)) {
      case [0xDD, 0x03]:
        GlobalModel().fet = temp[24].toRadixString(2).padLeft(8, '0');
        GlobalModel().v = [temp[4], temp[5]].decimal / 100.0;
        double a = [temp[6], temp[7]].decimal * 1.0;
        a = a < 0x8000 ? a : a - 0x10000;
        //如果FET控制状态最高位为1，则单位是100mA
        if (GlobalModel().fet[0] == '1') {
          GlobalModel().a = a / 10.0;
          GlobalModel().c = [temp[8], temp[9]].decimal / 10.0;
          GlobalModel().total_c = [temp[10], temp[11]].decimal / 10.0;
        } else {
          //默认单位10mA
          GlobalModel().a = a / 100.0;
          GlobalModel().c = [temp[8], temp[9]].decimal / 100.0;
          GlobalModel().total_c = [temp[10], temp[11]].decimal / 100.0;
        }

        GlobalModel().repeat = [temp[12], temp[13]].decimal;

        ///2个字节，16bit表示日期，
        ///例如 0x2078     二进制 = 0010 0000 0111 1000
        ///从高到低，依次高7位表示年： 0010 000
        ///     高8位到高11位表示月：         0 011
        ///    高12位到高16位表示日：              1 1000
        int product = [temp[14], temp[15]].decimal;
        int day = product & 0x1F;
        int month = product & 0x1E0;
        int year = product >> 9 + 2000;
        GlobalModel().product =
            '${year}/${month.toRadixString(10).padLeft(2, '0')}/${day.toRadixString(10).padLeft(2, '0')}';

        GlobalModel().balanced1 = [temp[16], temp[17]].decimal.toRadixString(2).padLeft(2, '0');
        GlobalModel().balanced2 = [temp[18], temp[19]].decimal.toRadixString(2).padLeft(2, '0');
        GlobalModel().protect = [temp[20], temp[21]].decimal.toRadixString(2).padLeft(2, '0');
        GlobalModel().version = temp[22].toRadixString(16);
        GlobalModel().rsoc = temp[23];

        GlobalModel().batter_num = temp[25];
        GlobalModel().ntc_num = temp[26];

        GlobalModel().ntc_list = List.generate(temp[26], ($0) {
          int index = 27 + $0 * 2; // 计算正确的索引
          double result = [temp[index], temp[index + 1]].decimal - 2731;
          result = (result / 10).roundDouble(1);
          return result;
        }).toList();
        break;
      case [0xDD, 0x04]:
        int v_num = temp[3];
        GlobalModel().list_v = List.generate(v_num, ($0) {
          int index = 4 + $0 * 2;
          double result = [temp[index], temp[index + 1]].decimal / 100.0;
          result = result.roundDouble(1);
          return result;
        }).toList();
        break;
      case [0xDD, 0x05]:
        break;
      case [0xDD, 0x0A]:
        if (listEquals(temp.sublist(2, 4), [0x00, 0x02])) {
          GlobalModel().openSoc = temp[5] == 0x01;
        }
        break;
      default:
        break;
    }
  }
}

class GlobalController extends GetxController {
  final Rx<GlobalModel> defaultModel = GlobalModel.instance.obs; // 只创建一次

  void updateDefault(void Function(GlobalModel item) fn) {
    defaultModel.update((model) {
      if (model != null) {
        fn(model);
      }
    });
  }
}
